/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */

package desarrollosoft.ghce.dao.implementaciones;

import desarrollosoft.ghce.dao.interfaces.IEstudioDAO;
import desarrollosoft.ghce.entidades.Componente;
import desarrollosoft.ghce.entidades.Estudio;
import desarrollosoft.ghce.entidades.EstudioImaginologia;
import desarrollosoft.ghce.entidades.EstudioLaboratorio;
import desarrollosoft.ghce.entidades.Gravedad;
import desarrollosoft.ghce.entidades.Imagen;
import desarrollosoft.ghce.entidades.Paciente;
import desarrollosoft.ghce.entidades.Plantilla;
import desarrollosoft.ghce.entidades.PlantillaEstudioImagenes;
import desarrollosoft.ghce.entidades.PlantillaEstudioLaboratorio;
import desarrollosoft.ghce.entidades.Profesional;
import desarrollosoft.ghce.entidades.ResultadoComponente;
import java.util.Date;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.NoResultException;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

/**
 *
 * @author ariel
 */
@Repository("estudioDAO")
public class EstudioDAO implements IEstudioDAO {

    @PersistenceContext
    private EntityManager entityManager;
    
    @Override
    public Estudio obtenerMasReciente(Plantilla plantilla, Paciente paciente) {
        Query consultaEstudioMasReciente = entityManager.createQuery(
                "SELECT e FROM Estudio e WHERE e.plantilla = :plantilla AND e.paciente = :paciente ORDER BY e.fecha DESC"
        );
        consultaEstudioMasReciente.setParameter("plantilla", plantilla);
        consultaEstudioMasReciente.setParameter("paciente", paciente);
        consultaEstudioMasReciente.setMaxResults(1);

        Estudio estudioConsultado;
        try {
            estudioConsultado = (Estudio) consultaEstudioMasReciente.getSingleResult();
            return estudioConsultado;
        } catch (NoResultException ex) {
            return null;
        }
    }

    @Override
    @Transactional(propagation = Propagation.MANDATORY)
    public void eliminar(Estudio estudio) {
        if (estudio instanceof EstudioImaginologia) {
            EstudioImaginologia estudioImaginologia = (EstudioImaginologia) estudio;
            Query consulta = entityManager.createQuery(
                    "SELECT i FROM Imagen i WHERE i.estudioImaginologia = :estudioImaginologia"
            );
            consulta.setParameter("estudioImaginologia", estudioImaginologia);
            List<Imagen> listaImagenesEstudio = consulta.getResultList();
            for (Imagen imagen : listaImagenesEstudio) {
                entityManager.remove( entityManager.merge(imagen) ); // borro todas las imagenes
            }
            entityManager.remove( entityManager.merge(estudioImaginologia) );
        } else if (estudio instanceof EstudioLaboratorio ) {
            EstudioLaboratorio estudioLaboratorio = (EstudioLaboratorio) estudio;
            Query consulta = entityManager.createQuery(
                    "SELECT r FROM ResultadoComponente r JOIN r.estudioLaboratorio e WHERE e = :estudio"
            );
            consulta.setParameter("estudio", estudioLaboratorio);
            List<ResultadoComponente> listaResultados = consulta.getResultList();
            for (ResultadoComponente resultado : listaResultados) {
                entityManager.remove( entityManager.merge(resultado) ); // borro todos los resultados
            }
            entityManager.remove( entityManager.merge(estudioLaboratorio) );// borro el estudio
        }
    }

    private Gravedad obtenerGravedadMinima() {
        Query consulta = entityManager.createQuery(
                "SELECT g FROM Gravedad g WHERE g.valor = (SELECT MIN(g.valor) FROM Gravedad g)"
        );
        return (Gravedad) consulta.getSingleResult();
    }

    @Override
    @Transactional(propagation = Propagation.MANDATORY)
    public void pedir(Plantilla plantillaElegida, Paciente paciente, Profesional profesionalActual) {
        
        if (plantillaElegida instanceof PlantillaEstudioLaboratorio ) {
            PlantillaEstudioLaboratorio plantillaEstudioLaboratorio = (PlantillaEstudioLaboratorio) plantillaElegida;
            Query consultaComponentes = entityManager.createQuery(
                    "SELECT c FROM Componente c JOIN c.plantillaEstudioLaboratorio p WHERE p = :plantillaEstudioLaboratorio"
            );
            consultaComponentes.setParameter("plantillaEstudioLaboratorio", plantillaEstudioLaboratorio);
            List<Componente> listaComponentes = consultaComponentes.getResultList();
            
            // creo estudio laboratorio (que hereda de elemento)
            EstudioLaboratorio estudioLaboratorio = new EstudioLaboratorio();
            estudioLaboratorio.setProfesional(profesionalActual);
            estudioLaboratorio.setFecha(new Date());
            estudioLaboratorio.setPlantillaEstudio(plantillaEstudioLaboratorio);
            estudioLaboratorio.setGravedad(obtenerGravedadMinima());
            estudioLaboratorio.setPlantilla(plantillaEstudioLaboratorio);
            estudioLaboratorio.setPaciente(paciente);
            
            for (Componente componente : listaComponentes) { // creo todos los resultados componentes para el estudio
                ResultadoComponente resultadoComponente = new ResultadoComponente();
                resultadoComponente.setComponente(componente);
                resultadoComponente.setEstudioLaboratorio(estudioLaboratorio);
                entityManager.persist(resultadoComponente);
            }
            
            entityManager.persist(estudioLaboratorio);// persisto el estudio de laboratorio
            
        } else { // es estudio de imaginologia
            PlantillaEstudioImagenes plantillaEstudioImagenes = (PlantillaEstudioImagenes) plantillaElegida;
            
            EstudioImaginologia estudioImaginologia = new EstudioImaginologia();
            estudioImaginologia.setProfesional(profesionalActual);
            estudioImaginologia.setGravedad(obtenerGravedadMinima());
            estudioImaginologia.setFecha(new Date());
            estudioImaginologia.setPaciente(paciente);
            estudioImaginologia.setPlantillaEstudioImagenes(plantillaEstudioImagenes);
            estudioImaginologia.setPlantilla(plantillaEstudioImagenes);
            
            entityManager.persist(estudioImaginologia); // lo persisto
        }
    }

    @Override
    public boolean estaTerminado(Estudio estudio) {
        if (estudio instanceof EstudioLaboratorio) {
            EstudioLaboratorio estudioLaboratorio = (EstudioLaboratorio) estudio;
            Query consulta = entityManager.createQuery(
                    "SELECT r FROM ResultadoComponente r JOIN r.estudioLaboratorio e WHERE e = :estudio"
            );
            consulta.setParameter("estudio", estudioLaboratorio);
            List<ResultadoComponente> listaResultados = consulta.getResultList();
            
            for (ResultadoComponente resultado : listaResultados) {
                if (resultado.getValor() == null) {
                    return false;
                }
            }
            return true;
        } else { // sino, es estudio de imaginologia
            Query consulta = entityManager.createQuery(
                    "SELECT COUNT(i) FROM Imagen i WHERE i.estudioImaginologia = :estudioImaginologia"
            );
            EstudioImaginologia estudioImaginologia = (EstudioImaginologia) estudio;
            consulta.setParameter("estudioImaginologia", estudioImaginologia);
            Long cantidadImagenes = (Long) consulta.getSingleResult();
            Long cantidadMinimaImagenes = new Long(estudioImaginologia.getPlantillaEstudioImagenes().getCantidadMinimaImagenes());
            if (cantidadImagenes < cantidadMinimaImagenes) {
                return false;
            }
            return true;
        }
    }

    @Override
    @Transactional(propagation = Propagation.MANDATORY)
    public void modificar(EstudioLaboratorio estudioLaboratorio) {
        entityManager.merge(estudioLaboratorio);
    }

    @Override
    @Transactional(propagation = Propagation.MANDATORY)
    public void modificarEstudioImaginologia(EstudioImaginologia estudioImaginologia) {
        entityManager.merge(estudioImaginologia);
    }
    
}
